class iGameWeapon extends UDKWeapon
	classgroup(iGame)
	hidecategories(Movement, Debug, Display, Attachment, Collision, Physics, Advanced, Object)
	nativereplication
	placeable;


var protected ParticleSystemComponent			Aim;
var(Effects) protected const ParticleSystem	    AimTemplate;

/** projectile class which is used when weapon fires */
var(Weapon) const iGameProjectile ProjectileTemplate;

/** Main weapon socket where weapon will be attached */
var(Weapon) const public name WeaponSocket;

/** Max ammo count */
var int MaxAmmoCount;
//var int AmmoCount;

/** Holds the amount of ammo used for a given shot */
var array<int> ShotCost;

//var MeshComponent    OverlayMesh;

//=============================================================================
// Animations
//=============================================================================
var bool bSuppressSounds;

/** Animation to play when the weapon is fired */
var(Animations)	array<name>	WeaponFireAnim;

/** Animation to play when the weapon is Put Down */
var(Animations) name	WeaponPutDownAnim;

/** Animation to play when the weapon is Equipped */
var(Animations) name	WeaponEquipAnim;

var(Animations) array<name> WeaponIdleAnims;

var(Animations) float DelayBeforeFire; //for play fire anim first

//=============================================================================
// Sounds
//=============================================================================
/** Sound to play when the weapon is fired */
var(Sounds)	array<SoundCue>	WeaponFireSnd;

/** Sound to play when the weapon is Put Down */
var(Sounds) SoundCue 	WeaponPutDownSnd;

/** Sound to play when the weapon is Equipped */
var(Sounds) SoundCue 	WeaponEquipSnd;

//=============================================================================
//  Muzzle Flash
//=============================================================================
/** Holds the name of the socket to attach a muzzle flash too */
var(Weapon) const name	FireEffectSocket;

/** Muzzle flash PSC and Templates*/
var protected ParticleSystemComponent	MuzzleFlashPSC;

/** Particle Systems for our firemodes */
var(Weapon) const ParticleSystem			MuzzleFlashPSCTemplate;

/** How long the Muzzle Flash should be there */
var(Weapon) const float					MuzzleFlashDuration;

/** Whether muzzleflash has been initialized */
var bool					bMuzzleFlashAttached;

/*********************************************************************************************
Replication
**********************************************************************************************/
simulated event ReplicatedEvent(name VarName)
{
	if ( VarName == 'AmmoCount' )
	{
		if ( !HasAnyAmmo() )
		{
			WeaponEmpty();
		}
	}
	else
	{
		Super.ReplicatedEvent(VarName);
	}
}

client reliable simulated function ClientEndFire(byte FireModeNum)
{
	if (Role != ROLE_Authority)
	{
		ClearPendingFire(FireModeNum);
		EndFire(FireModeNum);
	}
}

/*********************************************************************************************
Functions
**********************************************************************************************/
simulated function AttachWeaponTo( SkeletalMeshComponent MeshCpnt, optional Name aSocketName )
{
	local iGamePawn P;
	local name lSocketNameAttachTo;

	P = iGamePawn(Instigator);

	if (P != none)
	{
		Mesh.SetShadowParent(P.Mesh); //and the shadows

		lSocketNameAttachTo = aSocketName;

		SetBase(P,,P.Mesh, lSocketNameAttachTo);
		P.Mesh.AttachComponentToSocket(Mesh, lSocketNameAttachTo);

		if (OverlayMesh != none)
		{
			P.Mesh.AttachComponentToSocket(OverlayMesh, lSocketNameAttachTo);
		}
	}

	SetHidden(false);
}

simulated function CreateOverlayMesh()
{
	if (WorldInfo.NetMode != NM_DedicatedServer)
	{
		OverlayMesh = new(self) Mesh.Class;
		OverlayMesh.SetScale(1.05);
		SkeletalMeshComponent(OverlayMesh).SetSkeletalMesh(SkeletalMeshComponent(Mesh).SkeletalMesh);
		OverlayMesh.SetOwnerNoSee(false);
		OverlayMesh.SetOnlyOwnerSee(false);
		SkeletalMeshComponent(OverlayMesh).AnimSets = SkeletalMeshComponent(Mesh).AnimSets;
		SkeletalMeshComponent(OverlayMesh).SetParentAnimComponent(SkeletalMeshComponent(Mesh));
		SkeletalMeshComponent(OverlayMesh).bUpdateSkelWhenNotRendered = false;
		SkeletalMeshComponent(OverlayMesh).bIgnoreControllersWhenNotRendered = true;
		SkeletalMeshComponent(OverlayMesh).bOverrideAttachmentOwnerVisibility = true;

		if (UDKSkeletalMeshComponent(OverlayMesh) != none)
		{
			UDKSkeletalMeshComponent(OverlayMesh).SetFOV(UDKSkeletalMeshComponent(Mesh).FOV);
		}
	}
}

/**
 * Apply a given overlay material to the overlay mesh.
 */
simulated function SetOverlayMaterial(MaterialInterface NewOverlay)
{	
	local int i;

	if (OverlayMesh == None)
	{
		CreateOverlayMesh();
	}
	for (i=0; i < OverlayMesh.GetNumElements(); i++)
	{
		OverlayMesh.SetMaterial(i, NewOverlay);
	}
	if (!OverlayMesh.bAttached)
	{
		AttachComponent(OverlayMesh);
	}
}

function bool isOverlayAttached()
{
	return OverlayMesh.bAttached;
}

simulated function ReattachWeaponMesh()
{
	DetachComponent(Mesh);
	AttachComponent(Mesh);
}

/**
 * Detach weapon from skeletal mesh
 */
simulated function DetachFrom( SkeletalMeshComponent MeshCpnt )
{
	// Weapon Mesh Shadow
	if ( Mesh != None )
	{
		Mesh.SetShadowParent(None);
		Mesh.SetLightEnvironment(None);
		// muzzle flash effects
		if (MuzzleFlashPSC != None)
		{
			SkeletalMeshComponent(Mesh).DetachComponent(MuzzleFlashPSC);
		}
	}
	if ( MeshCpnt != None )
	{
		// detach weapon mesh from player skelmesh
		if ( Mesh != None )
		{
			MeshCpnt.DetachComponent( mesh );
		}

		if ( OverlayMesh != none )
		{
			MeshCpnt.DetachComponent( OverlayMesh );
		}
	}

	GotoState('');
}

simulated function DetachOverlayMesh()
{
	//OverlayMesh.SetHidden(true); //hide the weapon when inactive
	OverlayMesh.SetShadowParent(none); //just in case
	//Instigator.Mesh.DetachComponent(OverlayMesh); //might as well, saves us a transform
	DetachComponent(OverlayMesh); //might as well, saves us a transform
}

simulated function DetachWeapon()
{
	super.DetachWeapon();
	SetHidden(true); //hide the weapon when inactive
	Mesh.SetShadowParent(none); //just in case
	Instigator.Mesh.DetachComponent(Mesh); //might as well, saves us a transform
}

/** Pull out & ready the weapon */
simulated function Activate()
{
	super.Activate();
	AttachWeaponTo(Instigator.Mesh, WeaponSocket);

	if (Aim != none)
	{
		Aim.DeactivateSystem();
		Aim = none;
	}
	Aim = ShowEffect(AimTemplate, FireEffectSocket);
}

/** Hide the weapon */
simulated function PutDownWeapon()
{
	super.PutDownWeapon();
	DetachWeapon();

	if (Aim != none)
	{
		Aim.DeactivateSystem();
		Aim = none;
	}
}

/**
 * Show the weapon being put away
 */
simulated function PlayWeaponPutDown()
{
	// Play the animation for the weapon being put down

	if ( WeaponPutDownAnim != '' )
		PlayWeaponAnimation( WeaponPutDownAnim, PutDownTime );

	// play any associated sound
	if ( WeaponPutDownSnd != None )
		WeaponPlaySound( WeaponPutDownSnd );
}

simulated event SetPosition(UDKPawn Holder)
{
	local rotator NewRotation;

	// Adjust it in the world
	SetLocation(Holder.Location);

	SetBase(Holder);

	NewRotation = (Holder.Controller == None) ? Holder.GetBaseAimRotation() : Holder.Controller.Rotation;

	SetRotation(NewRotation);
}

/**
 * Tells the weapon to play a firing sound (uses CurrentFireMode)
 */
simulated function PlayFiringSound()
{
	if (CurrentFireMode<WeaponFireSnd.Length)
	{
		// play weapon fire sound
		if ( WeaponFireSnd[CurrentFireMode] != None )
		{
			MakeNoise(1.0);
			WeaponPlaySound( WeaponFireSnd[CurrentFireMode] );
		}
	}
}

/**
 * This function handles playing sounds for weapons.  How it plays the sound depends on the following:
 *
 * If we are a listen server, then this sound is played and replicated as normal
 * If we are a remote client, but locally controlled (ie: we are on the client) we play the sound and don't replicate it
 * If we are a dedicated server, play the sound and replicate it to everyone BUT the owner (he will play it locally).
 *
 *
 * @param	Sound	- The Source Cue to play
 */
simulated function WeaponPlaySound(SoundCue Sound, optional float NoiseLoudness)
{
	// if we are a listen server, just play the sound.  It will play locally
	// and be replicated to all other clients.
	if( Sound != None && Instigator != None && !bSuppressSounds  )
	{
		Instigator.PlaySound(Sound, false, true);
	}
}


/*********************************************************************************************
 * State Active
 * 
 *********************************************************************************************/
simulated state Active
{

	simulated event OnAnimEnd(AnimNodeSequence SeqNode, float PlayedTime, float ExcessTime)
	{
		local int IdleIndex;

		if ( WorldInfo.NetMode != NM_DedicatedServer && WeaponIdleAnims.Length > 0 )
		{
			IdleIndex = Rand(WeaponIdleAnims.Length);
			PlayWeaponAnimation(WeaponIdleAnims[IdleIndex], 0.0, true);
		}
	}

	simulated function PlayWeaponAnimation( Name Sequence, float fDesiredDuration, optional bool bLoop, optional SkeletalMeshComponent SkelMesh)
	{
		Global.PlayWeaponAnimation(Sequence, fDesiredDuration,bLoop,SkelMesh);
		ClearTimer('OnAnimEnd');
		if (!bLoop)
		{
			SetTimer(fDesiredDuration,false,'OnAnimEnd');
		}
	}

	simulated function bool ShouldLagRot()
	{
		return true;
	}

	/** Initialize the weapon as being active and ready to go. */
	simulated function BeginState( Name PreviousStateName )
	{
		OnAnimEnd(none, 0.f, 0.f);

		Super.BeginState(PreviousStateName);

		if (InvManager != none && InvManager.LastAttemptedSwitchToWeapon != none)
		{
			if (InvManager.LastAttemptedSwitchToWeapon != self)
			{
				InvManager.LastAttemptedSwitchToWeapon.ClientWeaponSet(true);
			}
			InvManager.LastAttemptedSwitchToWeapon = none;
		}
	}
}

/*********************************************************************************************
 * State WeaponEquipping
 * 
 *********************************************************************************************/
simulated state WeaponEquipping
{
	simulated event BeginState(Name PreviousStateName)
	{
        AttachWeaponTo(Instigator.Mesh);
		Super.BeginState(PreviousStateName);
	}
}

/**
 * Show the weapon begin equipped
 */
simulated function PlayWeaponEquip()
{
	// Play the animation for the weapon being put down

	if ( WeaponEquipAnim != '' )
		PlayWeaponAnimation( WeaponEquipAnim, EquipTime );

	// play any assoicated sound
	if ( WeaponEquipSnd != None )
		WeaponPlaySound( WeaponEquipSnd );
}

/*********************************************************************************************
 * State WeaponFiring
 * This is the default Firing State.  It's performed on both the client and the server.
 *********************************************************************************************/
simulated state WeaponFiring
{
	simulated event ReplicatedEvent(name VarName)
	{
		if ( VarName == 'AmmoCount' && !HasAnyAmmo() )
		{
			return;
		}

		Global.ReplicatedEvent(VarName);
	}

	/**
	 * We override BeginFire() so that we can check for zooming and/or empty weapons
	 */
	simulated function BeginFire( Byte FireModeNum )
	{
		Global.BeginFire(FireModeNum);

		// No Ammo, then do a quick exit.
		if( !HasAmmo(FireModeNum) )
		{
			WeaponEmpty();
			return;
		}
	}

	/**
	 * When we are in the firing state, don't allow for a pickup to switch the weapon
	 */
	simulated function bool DenyClientWeaponSet()
	{
		return true;
	}

	simulated event BeginState( Name PreviousStateName ) // UNUSED. functions moved to begin: label
	{
		// Play Weapon fire animation
		if ( CurrentFireMode < WeaponFireAnim.Length && WeaponFireAnim[CurrentFireMode] != '' )
		{
			PlayWeaponAnimation( WeaponFireAnim[CurrentFireMode], GetFireInterval(CurrentFireMode));
		}
	}



Begin:
	Sleep(DelayBeforeFire);                                         // start fire anim
	FireAmmunition();                                               // do fire
	Sleep(GetFireInterval(CurrentFireMode) - DelayBeforeFire);      // end fire anim
	HandleFinishedFiring();                                         // end fire
}

simulated function FireAmmunition()
{
	// Use ammunition to fire
	ConsumeAmmo( CurrentFireMode );

	// if this is the local player, play the firing effects
	PlayFiringSound();

	// Handle the different fire types
	switch( WeaponFireTypes[CurrentFireMode] )
	{
		case EWFT_InstantHit:   InstantFire();
		break;

		case EWFT_Projectile:   ProjectileFire();
		break;

		case EWFT_Custom:       CustomFire();
		break;
	}

	NotifyWeaponFired( CurrentFireMode );
}

/*********************************************************************************************
 Muzzle Flash Methods
**********************************************************************************************/
/**
 * PlayFireEffects Is the root function that handles all of the effects associated with
 * a weapon.  This function creates the 1st person effects.  It should only be called
 * on a locally controlled player.
 */
simulated function PlayFireEffects( byte FireModeNum, optional vector HitLocation )
{
	// Start muzzle flash effect
	CauseMuzzleFlash();
}

simulated function StopFireEffects(byte FireModeNum)
{
	StopMuzzleFlash();
}

simulated function PlayWeaponAnimation(name Sequence, float fDesiredDuration, optional bool bLoop, optional SkeletalMeshComponent SkelMesh)
{
	if (Mesh != None && Mesh.bAttached)
	{
		Super.PlayWeaponAnimation(Sequence, fDesiredDuration, bLoop, SkelMesh);
	}
}

/**
 * Called on a client, this function Attaches the MuzzleFlashParticleSystemComponent
 */
function AttachMuzzleFlash()
{
	// Attach the Muzzle Flash
	bMuzzleFlashAttached = true;
	if (  Mesh != none )
	{
	    //if our weapon has at least one muzzle flash
	    //lets attach our muzzle flash particle system component
		if ( MuzzleFlashPSCTemplate!=none)
		{
			MuzzleFlashPSC = new(Outer)class'ParticleSystemComponent';
			MuzzleFlashPSC.bAutoActivate = false;
			//MuzzleFlashPSC.SetDepthPriorityGroup(SDPG_Foreground);
			MuzzleFlashPSC.SetOwnerNoSee(true);
			//MuzzleFlashPSC.SetFOV(UDKSkeletalMeshComponent(SKMesh).FOV);
			SkeletalMeshComponent(Mesh).AttachComponentToSocket(MuzzleFlashPSC, FireEffectSocket);
			MuzzleFlashPSC.SetRotation(Instigator.Rotation);
		}
	}
}

/**
 * Causes the muzzle flash to turn on and setup a time to
 * turn it back off again.
 */
/** Causes the muzzle flash to turn on and setup a time to turn it back off again. */
event CauseMuzzleFlash()
{
	local ParticleSystem MuzzleTemplate;

    //Only proceed if our firing mode has a muzzle flash
	if (MuzzleFlashPSCTemplate != none)
	{
		if ( !bMuzzleFlashAttached )
		{
			AttachMuzzleFlash();
		}
		if (!MuzzleFlashPSC.bIsActive || MuzzleFlashPSC.bWasDeactivated)
		{
			MuzzleTemplate = MuzzleFlashPSCTemplate;

			//If our current PSC is using a different muzzle flash particle
			//Lets go ahead and swap it with the one we need
			if (MuzzleTemplate != MuzzleFlashPSC.Template)
			{
				MuzzleFlashPSC.SetTemplate(MuzzleTemplate);
			}
			SetMuzzleFlashParams(MuzzleFlashPSC);
			MuzzleFlashPSC.ActivateSystem();
		}
		// Set when to turn it off.
		SetTimer(MuzzleFlashDuration,false,'MuzzleFlashTimer');
	}
}

/**
 * Turns the MuzzleFlashPSC off
 */
event MuzzleFlashTimer()
{
	if (MuzzleFlashPSC != none)
	{
		MuzzleFlashPSC.DeactivateSystem();
	}
}

event StopMuzzleFlash()
{
	ClearTimer('MuzzleFlashTimer');
	MuzzleFlashTimer();

	if ( MuzzleFlashPSC != none )
	{
		MuzzleFlashPSC.DeactivateSystem();
	}
}

/**
 * Allows a child to setup custom parameters on the muzzle flash
 */

function SetMuzzleFlashParams(ParticleSystemComponent PSC)
{
	return;
}


/*********************************************************************************************
 * Ammunition / Inventory
 *********************************************************************************************/
function int GetAmmoCount()
{
	return AmmoCount;
}
 /*
 * Consumes some of the ammo
 */
function ConsumeAmmo( byte FireModeNum )
{
	// Subtract the Ammo
	AddAmmo(-ShotCost[FireModeNum]);
}

/**
 * This function is used to add ammo back to a weapon.  It's called from the Inventory Manager
 */
function int AddAmmo( int Amount )
{
	AmmoCount = Clamp(AmmoCount + Amount,0,MaxAmmoCount);
	return AmmoCount;
}


/**
 * Returns true if the ammo is maxed out
 */
function bool AmmoMaxed(int mode)
{
	return (AmmoCount >= MaxAmmoCount);
}

/**
 * This function checks to see if the weapon has any ammo available for a given fire mode.
 *
 * @param	FireModeNum		- The Fire Mode to Test For
 * @param	Amount			- [Optional] Check to see if this amount is available.  If 0 it will default to checking
 *							  for the ShotCost
 */
simulated function bool HasAmmo( byte FireModeNum, optional int Amount )
{
	if (Amount==0)
		return (AmmoCount >= ShotCost[FireModeNum]);
	else
		return ( AmmoCount >= Amount );
}

/**
 * returns true if this weapon has any ammo
 */
simulated function bool HasAnyAmmo()
{
	return ( ( AmmoCount > 0 ) || (ShotCost[0]==0) );
}

/**
 * This function retuns how much of the clip is empty.
 */
function float DesireAmmo(bool bDetour)
{
	return (1.f - float(AmmoCount)/MaxAmmoCount);
}

/**
 * Returns true if the current ammo count is less than the default ammo count
 */
function bool NeedAmmo()
{
	return ( AmmoCount < Default.AmmoCount );
}

/**
 * Cheat Help function the loads out the weapon
 *
 * @param 	bUseWeaponMax 	- [Optional] If true, this function will load out the weapon
 *							  with the actual maximum, not 999
 */
function Loaded(optional bool bUseWeaponMax)
{
	if (bUseWeaponMax)
		AmmoCount = MaxAmmoCount;
	else
		AmmoCount = 999;
}

/**
 * Called when the weapon runs out of ammo during firing
 */
simulated function WeaponEmpty()
{
	// If we were firing, stop
	if ( IsFiring() )
	{
		GotoState('Active');
	}

	if ( Instigator != none && Instigator.IsLocallyControlled() )
	{
		Instigator.InvManager.SwitchToBestWeapon( true );
	}
}

/*********************************************************************************************
 * Fire Fucntions
 *********************************************************************************************/
/**
 * Fires a projectile.
 * Spawns the projectile, but also increment the flash count for remote client effects.
 * Network: Local Player and Server
 */
simulated function Projectile ProjectileFire()
{
	local Projectile	SpawnedProjectile;
	local vector        lSocketLocation;
	local Rotator       lSocketRotation;
	local Rotator       ProjectileStartRot;
	local vector        ProjectileStartLoc;

	// tell remote clients that we fired, to trigger effects
	IncrementFlashCount();

	if( Role == ROLE_Authority )
	{
		if ( SkeletalMeshComponent(Mesh).GetSocketWorldLocationAndRotation(FireEffectSocket, lSocketLocation, lSocketRotation) )
		{
			ProjectileStartLoc = lSocketLocation;
			ProjectileStartRot = lSocketRotation;
		}
		else
		{
			ProjectileStartLoc = Instigator.Location;
			ProjectileStartRot = Instigator.Rotation;
		}

		ProjectileStartLoc.Z = Instigator.Location.Z; //fix Z

		// Spawn projectile
		SpawnedProjectile = Spawn(ProjectileTemplate.Class,,, ProjectileStartLoc, ProjectileStartRot, ProjectileTemplate, true);
		if( SpawnedProjectile != None && !SpawnedProjectile.bDeleteMe )
		{
			SpawnedProjectile.Init( Vector(GetAdjustedAim( ProjectileStartLoc )) );
		}

		//`log(" Pawn location = "$Instigator.Location);
		//`log(" Pawn Weapon location = "$Instigator.weapon.Location);
		//`log(" ProjectileStartLoc = "$ProjectileStartLoc);
		//`log(" GetAdjustedAim ="$Vector(GetAdjustedAim( ProjectileStartLoc )));

		// Return it up the line
		return SpawnedProjectile;
	}

	return None;
}

function bool CanAttack(Actor Other)
{
	local float Dist, CheckDist, OtherHeight;
	local vector HitLocation, HitNormal, projStart, TargetLoc;
	local Actor HitActor, TestActor;
	local iGameAIController B;

	if (Instigator == None || Instigator.Controller == None)
	{
		return false;
	}

	// check that target is within range
	Dist = VSize(Instigator.Location - Other.Location);
	if (Dist > WeaponRange)
	{
		return false;
	}

	projStart = bInstantHit ? InstantFireStartTrace() : GetPhysicalFireStartLoc();

	// check that can see target
	B = iGameAIController(Instigator.Controller);
	if (Instigator.Controller.LineOfSightTo(Other, projStart))
	{
		if (B != None && B.Focus == Other)
		{
			B.DoChangeFirePosition(false);
		}
	}
	else
	{
		if (!Other.bHasAlternateTargetLocation || !Instigator.Controller.LineOfSightTo(Other, projStart, true))
		{
			return false;
		}

		if (B != None && B.Focus == Other)
		{
			B.DoChangeFirePosition(true);
		}
	}

	if ( !bInstantHit && !bMeleeWeapon )
	{
		CheckDist = FMax(CheckDist, 0.5 * ProjectileTemplate.Speed);
		CheckDist = FMax(CheckDist, 300);
		CheckDist = FMin(CheckDist, VSize(Other.Location - Location));
	}

	// check that would hit target, and not a friendly
	TargetLoc = Other.GetTargetLocation(Instigator);
	if ( Pawn(Other) != None )
	{
		OtherHeight = Pawn(Other).GetCollisionHeight();
		TargetLoc.Z += 0.9 * OtherHeight;
	}

	// perform the trace
	if ( bInstantHit )
	{
		HitActor = GetTraceOwner().Trace(HitLocation, HitNormal, TargetLoc, projStart, true,,, TRACEFLAG_Bullet);
	}
	else
	{
		// for non-instant hit, ignore actors beyond a small distance that may move out of the way
		foreach GetTraceOwner().TraceActors( class'Actor', TestActor, HitLocation, HitNormal,
							TargetLoc, projStart,,, TRACEFLAG_Bullet )
		{
			if ( (TestActor.bBlockActors || TestActor.bProjTarget) &&
				(VSize(HitLocation - projStart) <= CheckDist || TestActor.IsStationary()) )
			{
				HitActor = TestActor;
				break;
			}
		}
	}

	if ( HitActor == None || HitActor == Other || (!HitActor.IsA('Pawn') ) || !WorldInfo.GRI.OnSameTeam(Instigator, HitActor) )
	{
		return true;
	}

	return false;
}

/**
* @returns position of trace start for instantfire()
*/
simulated function vector InstantFireStartTrace()
{
	return Instigator.GetWeaponStartTraceLocation();
}

/**
* @returns end trace position for instantfire()
*/
simulated function vector InstantFireEndTrace(vector StartTrace)
{
	return StartTrace + vector(GetAdjustedAim(StartTrace)) * GetTraceRange();
}

//=============================================================================
// Effects
//=============================================================================
simulated function ParticleSystemComponent ShowEffect(ParticleSystem aTemplate, name aSocketName)
{
	local ParticleSystemComponent lLastSpawnedEffect;

	if ( aTemplate != none )
	{
		lLastSpawnedEffect = new(Outer)class'ParticleSystemComponent';
		lLastSpawnedEffect.SetRotation(rot(0,0,0));
		lLastSpawnedEffect.SetTemplate(aTemplate);

		if (aSocketName != '')
		{
			SkeletalMeshComponent(Mesh).AttachComponentToSocket(lLastSpawnedEffect, aSocketName);
		}
		else AttachComponent(lLastSpawnedEffect);

		lLastSpawnedEffect.ActivateSystem();
	}

	return lLastSpawnedEffect;
}

//=============================================================================
// Default Properties
//=============================================================================
DefaultProperties
{
	Begin Object Class=UDKSkeletalMeshComponent Name=SkeletalMeshComponent0
		CollideActors=false
		AlwaysLoadOnClient=true
		AlwaysLoadOnServer=true
		MaxDrawDistance=10000
		bUseAsOccluder=FALSE
		bUpdateSkelWhenNotRendered=false
		bIgnoreControllersWhenNotRendered=true
		bOverrideAttachmentOwnerVisibility=true
		bAcceptsDynamicDecals=FALSE
	End Object
	Components.Add(SkeletalMeshComponent0)
	Mesh=SkeletalMeshComponent0

	ShotCost(0) = 0
	Spread(0) = 0.1

	FiringStatesArray(0) = WeaponFiring
	ShouldFireOnRelease(0) = 0

	FireInterval(0)=0

	WeaponFireTypes(0)=EWFT_Projectile

	FireEffectSocket=FireEffect

	EquipTime=+0.45
	PutDownTime=+0.33

	WeaponPutDownAnim=WeaponPutDown
	WeaponEquipAnim=WeaponEquip
	WeaponIdleAnims(0)=WeaponIdle
	WeaponFireAnim(0)=WeaponFire
	DefaultAnimSpeed=1.0

	weaponrange = 512
}